<?php

namespace App;

use App\Events\ThreadReceivedNewReply;
use App\Filters\ThreadsFilters;
use App\Traits\RecordsActivity;
use App\Traits\RecordVisits;
use Illuminate\Database\Eloquent\Model;

/**
 * App\Thread
 *
 * @property-read \App\Channel                                                       $channel
 * @property-read \App\User                                                          $creator
 * @property-read mixed                                                              $is_subscribed_to
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Reply[]              $replies
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\ThreadSubscription[] $subscriptions
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Thread filter($filters)
 * @mixin \Eloquent
 * @property int                                                                     $id
 * @property int                                                                     $user_id
 * @property int                                                                     $channel_id
 * @property int                                                                     $replies_count
 * @property string                                                                  $title
 * @property string                                                                  $body
 * @property \Carbon\Carbon|null                                                     $created_at
 * @property \Carbon\Carbon|null                                                     $updated_at
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Thread whereBody($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Thread whereChannelId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Thread whereCreatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Thread whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Thread whereRepliesCount($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Thread whereTitle($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Thread whereUpdatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Thread whereUserId($value)
 */
class Thread extends Model
{
    use RecordsActivity;

    protected $guarded = [];//todo 这意味着所有的属性都可以更新，后期会修复此安全隐患

    protected $with = ['creator', 'channel'];

    protected $appends = ['isSubscribedTo'];

    protected $casts = [
        'locked' => 'boolean',
    ];

    protected static function boot()
    {
        parent::boot();
        static::deleting(function ($thread) {
            $thread->replies->each->delete();
        });
        static::created(function ($thread) {
            $thread->update([
                'slug' => $thread->title,
            ]);
        });
    }

    public function setSlugAttribute($value)
    {
        $slug = str_slug($value);
        if (static::whereSlug($slug)->exists()) {
            $slug = "{$slug}-" . $this->id;
        }
        $this->attributes['slug'] = $slug;
    }

    public function path()
    {
        return "/threads/{$this->channel->slug}/{$this->slug}";
    }

    public function replies()
    {
        return $this->hasMany(Reply::class);
    }

    public function creator()
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    public function addReply($reply)
    {
        $reply = $this->replies()->create($reply);
        event(new ThreadReceivedNewReply($reply));//触发事件
//        $this->notifySubscribers($reply);
        return $reply;
    }

    public function channel()
    {
        return $this->belongsTo(Channel::class);
    }

    /**
     * @param                $query
     * @param ThreadsFilters $filters
     * @return mixed
     */
    public function scopeFilter($query, $filters)
    {
        return $filters->apply($query);
    }

    public function subscribe($userId = null)
    {
        $this->subscriptions()->create([
            'user_id' => $userId ?? auth()->id(),
        ]);
        return $this;
    }

    public function unsubscribe($userId = null)
    {
        $this->subscriptions()
            ->where('user_id', $userId ?? auth()->id())
            ->delete();
        return $this;
    }

    public function subscriptions()
    {
        return $this->hasMany(ThreadSubscription::class);
    }

    public function getIsSubscribedToAttribute()
    {
        return $this->subscriptions()
            ->where('user_id', auth()->id())
            ->exists();
    }


    public function hasUpdatedFor($user)
    {
        // Look in the cache for the proper key
        // compare that carbon instance with the $thread->updated_at
        $key = $user->visitedThreadCacheKey($this);
        return $this->updated_at > cache($key);
    }

    public function getRouteKeyName()
    {
        return 'slug';
    }

    public function markBestReply(Reply $reply)
    {
        $this->update(['best_reply_id' => $reply->id]);
    }
}
